DynamoDBでSQLのIN句のように複数条件を指定する
はじめに
私が担当しているプロジェクトではDynamoDBを使っています。複数のパーティションキーを指定してデータを取得したいのですが、何度もGetItemすると時間がかかるのでSQLのIN句のように一括で取得する方法がないか調べました。
テーブル
サンプルとして以下のようなemployee
テーブルを作成しました。
id がパーティションキーでname
, department_id
を属性として持っています。
パーティションキーを複数指定して一括で取得する
上記のテーブルからデータを取得するLambdaファンクションをPythonで実装してみました。キーを複数指定して一括して取得する場合はbatch_get_item
を使っています。パーティションキーのid
を複数指定できます。
import boto3 from boto3.dynamodb.conditions import Attr dynamodb = boto3.resource('dynamodb') def lambda_handler(event, context): requestItems = {'employee': {'Keys': [{'id': '00001'}, {'id': '00002'}]}} response = dynamodb.batch_get_item(RequestItems=requestItems) if "Responses" in response: items = response["Responses"].get('employee', []) for item in items: print(item) return
実行すると以下のような結果が出力されました。
{'id': '00001', 'department_id': '001', 'name': '名前1'} {'department_id': '001', 'id': '00002', 'name': '名前2'}
batch_get_item は便利ですが注意点があります。それは一度に取得できる件数、データ量に制限があることです。制限を超える場合は何回かに分ければ取得できます。詳しくは以下の公式のページをご覧ください。また、batch_get_item はテーブルに対してのみ実行でき、インデックスに対しては実行できません。
AWS SDK を使用して DynamoDB 項目のバッチを取得する - Amazon DynamoDB
パーティションキー以外の属性を複数指定して一括で取得する
次にパーティションキーではないdepartment_id
属性を条件にして一括取得しました。scanで全件取得した後にFilterExpressionで絞りこんでいます。
import boto3 from boto3.dynamodb.conditions import Attr dynamodb = boto3.resource('dynamodb') def lambda_handler(event, context): table= dynamodb.Table('employee') response = table.scan(FilterExpression=Attr("department_id").is_in(['001', '003'])) if "Items" in response: for item in response["Items"]: print(item) return
実行すると以下のような結果が出力されます。department_idが001と003のデータのみ取得できています。
{'department_id': '001', 'id': '00003', 'name': '名前3'} {'department_id': '001', 'id': '00002', 'name': '名前2'} {'id': '00001', 'department_id': '001', 'name': '名前1'} {'department_id': '003', 'id': '00006', 'name': '名前6'}
この方法の注意点はscanはテーブルの全データを取得するため、データ量が多いほどキャパシティを多く消費することです。許容できない場合はグローバルセカンダリインデックスを作成して1件づつqueryで取得したほうがよさそうです。
PartiQL
DynamoDBにはPartiQLというSQL互換の言語を使うことができます。PartiQLにはIN句も使えますがパーティションキー以外は上記の様にscanしていると思われます。詳しくは以下のドキュメントをご覧ください。
DynamoDB 用の PartiQL select ステートメント
最後に
今回調べたことは以上になります。パーティションキー以外での一括取得は中々難しそうだと感じました。何度もDynamoDBにリクエストしなくてもいいように設計時点で気を付けたいですね。